package com.uxwine.alarm;

import java.util.Calendar;

public class AlarmCalc
{
	
	public static long triggerTime(Alarm alarm)
	{
		final TimeRecord time = alarm.time;
		final TimeCycle cycle = alarm.cycle;
		return triggerTime(time, cycle).getTimeInMillis();
	}
	
	public static Calendar triggerTime(final TimeRecord time, final TimeCycle cycle)
	{
		
		if(cycle.isOnce())
		{
			//非周期的闹钟，返回一个非空即可
			final Calendar c = Calendar.getInstance();
			c.set(Calendar.YEAR, 0);
			return c;
		}
        
        //先搞定每年
        if(cycle.isEveryYear())
        {
        	return getByYear(time);        		
        }
        
        if(cycle.isEveryMonth())
        {
        	return getByMonth(time);
        }
        
        return getByDay(time, cycle);
	}
	
	private static Calendar getByDay(TimeRecord time, TimeCycle cycle)
	{
		// start with now
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(System.currentTimeMillis());

        int hour = time.get(TimeRecord.HOUR);
        int minute = time.get(TimeRecord.MINUTE);
        int nowHour = c.get(Calendar.HOUR_OF_DAY);
        int nowMinute = c.get(Calendar.MINUTE);

        // if alarm is behind current time, advance one day
        if (hour < nowHour  ||
            hour == nowHour && minute <= nowMinute) {
            c.add(Calendar.DAY_OF_YEAR, 1);
        }
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);

        int addDays = cycle.getNextAlarm(c);
        if (addDays > 0)
        	c.add(Calendar.DAY_OF_WEEK, addDays);
        return c;
	}
	
	private static Calendar getByMonth(TimeRecord time)
	{
		//zzm:下面计算一下周期的闹钟
        Calendar now = Calendar.getInstance();
        now.setTimeInMillis(System.currentTimeMillis());
        Calendar dist = Calendar.getInstance();  

        int day = time.get(TimeRecord.DATE);
        int hour = time.get(TimeRecord.HOUR);
        int min = time.get(TimeRecord.MINUTE);
        
        int nowYear = now.get(Calendar.YEAR);
        int nowMonth = now.get(Calendar.MONTH);
        
        
        setWithCheckMonth(dist, nowYear, nowMonth, day, hour, min);
        
        if(!dist.after(now))
        {
        	if(nowMonth == Calendar.DECEMBER)
        	{
        		nowYear++;
        		nowMonth = Calendar.JANUARY;
        	}
        	else
        	{
        		nowMonth ++;
        	}
        	setWithCheckMonth(dist, nowYear, nowMonth, day, hour, min);
        }

        dist.set(Calendar.SECOND, 0);
        dist.set(Calendar.MILLISECOND, 0);
        return dist;
	}
	
	private static void setWithCheckMonth(Calendar c, int y, int m, int d, int h, int mm)
	{		
		//排除了2.29, 2.30, 2.31的情况
		if(m == Calendar.FEBRUARY && d >= 29)
		{
			d = 29;
			setWithLeap(c, y, m, d, h, mm);
			return;
		}
		
		if((d == 31) && 
				(m == Calendar.APRIL ||
				m == Calendar.JUNE || 
				m == Calendar.SEPTEMBER ||
				m == Calendar.NOVEMBER))
		{
			d = 30;		
		}
		c.set(y, m, d, h, mm);
	}
	
	private static Calendar getByYear(TimeRecord time)
	{
		//zzm:下面计算一下周期的闹钟
        Calendar now = Calendar.getInstance();
        now.setTimeInMillis(System.currentTimeMillis());
        Calendar dist = Calendar.getInstance();        

        int month = time.get(TimeRecord.MONTH);
        int day = time.get(TimeRecord.DATE);
        int hour = time.get(TimeRecord.HOUR);
        int min = time.get(TimeRecord.MINUTE);
        
        int nowYear = now.get(Calendar.YEAR);
        setWithLeap(dist, nowYear, month, day, hour, min);
        
        if(!dist.after(now))
        	setWithLeap(dist, nowYear + 1, month, day, hour, min);
        
        dist.set(Calendar.SECOND, 0);
        dist.set(Calendar.MILLISECOND, 0);        
        return dist;
	}
	
	private static void setWithLeap(Calendar c, int y, int m, int d, int h, int mm)
	{
		c.set(y, m, ((!isLeap(y)) && (m == Calendar.FEBRUARY && d == 29)) ? 28 : d, h, m, 0);
	}
	
	private static boolean isLeap(int year)
	{
		return ((year%4==0)&&(year%100!=0)||(year%400==0));
	}
}
